//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of your Microsoft Windows CE
// Source Alliance Program license form.  If you did not accept the terms of
// such a license, you are not authorized to use this source code.
//
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2003 Intrinsyc Europe Ltd.
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2004 Siemens AG
//
// Version: 1.1.2.5
// Date:    11. Jan. 2006
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright 2006 Marvell International Ltd.
// All Rights Reserved
//

#include <windows.h>
#include <types.h>
#include <memory.h>
#include <linklist.h>
#include <windev.h>
#include <pkfuncs.h>
#include <pegdser.h>
#include <devload.h>
#include <dbgapi.h>
#include <ril.h>
#include "rhaapi.h"
#include "rhadll.h"

#include <ceddk.h>
#include "xllp_i2c.h"
#include "monahans.h"

#include "GPX_XLLP.h"

/* The macro define must have keep same with the define in wavemain.h */
#define WPDM_PRIVATE WM_USER+10
#define WPDM_PRIVATE_SETUP_PHONE_PATH       WPDM_PRIVATE+3 // enable the phone path from the telephone modem/hardware
#define WPDM_PRIVATE_DISABLE_PHONE_PATH     WPDM_PRIVATE+4 // disable the phone path from the telephone modem/hardware


#ifdef DEBUG_FILE
int DbgWrite(LPWSTR lpszFmt, ...);
CRITICAL_SECTION    csDbgCritSect;
#endif

#ifdef DEBUG
DBGPARAM dpCurSettings = {
    TEXT("RhaDll"), {
        TEXT("Init"),TEXT("Open"),TEXT("Read"),TEXT("Write"),
        TEXT("Close"),TEXT("Ioctl"),TEXT("Thread"),TEXT("Events"),
        TEXT("CritSec"),TEXT("FlowCtrl"),TEXT("Info"),TEXT("User Read"),
        TEXT("Alloc"),TEXT("Function"),TEXT("Warning"),TEXT("Error")},
//  0xFFFF
    0xC013
};
#endif

BOOL g_fRadioOn = FALSE;
BOOL g_fRHADLLInitFlag = FALSE;

/* For I2C Setting */
volatile XLLP_I2C_T *gpI2CRegs = NULL;    
volatile XLLP_OST_T *gpOSTRegs = NULL;    
volatile XLLP_CLKMGR_T   *gpDCCLKReg = NULL;
volatile unsigned int *gpMFPRegs = NULL;
volatile XLLP_MFP_RM_DB_ID_T *gpMfpRMDb = NULL;
volatile HANDLE gMfpRMDbHandle = NULL;

#define  RHA_MFP_TMP_SIZE  0x700

#define PCA9539BS               0
#define MAX7321                  1

#define GPIO_EXPANDER       MAX7321

/*
 @doc INTERNAL
 @func  BOOL | RhaDllEntry | Process attach/detach api.
 *
 @rdesc The return is a BOOL, representing success (TRUE) or failure (FALSE).
 */
BOOL WINAPI RhaDllEntry(HINSTANCE DllInstance, INT Reason, LPVOID Reserved)
{
    switch(Reason) {
        case DLL_PROCESS_ATTACH:
#ifdef DEBUG
#ifndef DEBUG_FILE
            DEBUGREGISTER(DllInstance);
#endif
//          DEBUGMSG (ZONE_INIT,(TEXT("RHADLL: DLL_PROCESS_ATTACH\r\n")));
#endif
            break;

        case DLL_PROCESS_DETACH:
#ifdef DEBUG
//          DEBUGMSG (ZONE_INIT,(TEXT("RHADLL: DLL_PROCESS_DETACH\r\n")));
#endif
            break;
    }
    return TRUE;
}

//
// First function called by the RIL after loading of the library
//
void RHA_Init(void)
{
    BOOL bFirstInit = FALSE;
    PHYSICAL_ADDRESS ioPhysicalBase = {0, 0};
    
    if (g_fRHADLLInitFlag)
    {
        RETAILMSG(1, (TEXT("[RIL] RHA_Init had already been init before\r\n")));
        return;        
    }
    
    ioPhysicalBase.QuadPart = MONAHANS_BASE_REG_PA_CLKMGR;
    gpDCCLKReg = (P_XLLP_CLKMGR_T)MmMapIoSpace(ioPhysicalBase, sizeof(XLLP_CLKMGR_T), FALSE);

    if (!gpDCCLKReg)
    {
        RETAILMSG(1, (TEXT("[RIL] RHA_Init ***Failed to allocate Clkmgr channel\r\n")));
        return;
    }

    ioPhysicalBase.QuadPart = MONAHANS_BASE_REG_PA_I2C;
    gpI2CRegs = (P_XLLP_I2C_T)MmMapIoSpace(ioPhysicalBase, sizeof(XLLP_I2C_T),FALSE);

    if(!gpI2CRegs)
    {
        RETAILMSG(1, (TEXT("[RIL] RHA_Init ***Failed to allocate I2C channel\r\n")));
        return;
    }

    ioPhysicalBase.QuadPart = MONAHANS_BASE_REG_PA_OST;
    gpOSTRegs = (volatile XLLP_OST_T*)MmMapIoSpace(ioPhysicalBase, sizeof(XLLP_OST_T),FALSE);
    
    if (!gpOSTRegs)
    {
        RETAILMSG(1, (TEXT("[RIL] RHA_Init ***Failed to allocate OST channel\r\n")));
        return;
    }

    ioPhysicalBase.QuadPart = MONAHANS_BASE_REG_PA_GPIO + 0x10000;
    gpMFPRegs = (volatile unsigned int *)MmMapIoSpace(ioPhysicalBase, RHA_MFP_TMP_SIZE, FALSE);
    
    if (!gpMFPRegs)
    {
        RETAILMSG(1, (TEXT("[RIL] RHA_Init ***Failed to allocate MFP channel\r\n")));
        return;
    }

    /* Claim memory-mapped file for sharing MfpRmDb information. */
    gMfpRMDbHandle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
                                       0, XLLP_MFP_RM_DB_SIZE, MFPRMDB_SHARED_FILENAME );

    if (!gMfpRMDbHandle)        
    {
        RETAILMSG(1, (TEXT("[RIL] RHA_Init *** Fail to CreateFileMapping(MFPRMDB_SHARED_FILENAME)\r\n")));
        return;
    } 

    // We need to tell if it's first or sequent call of  CreateFileMapping(MFPRMDB_SHARED_FILENAME)
    if (ERROR_ALREADY_EXISTS != GetLastError())
    {
        // The first initialization of this memory-mapped file.
        RETAILMSG(1, (TEXT("[RIL] RHA_Init ***First call of CreateFileMapping(MFPRMDB_SHARED_FILENAME)! \r\n")));        
        bFirstInit = TRUE;        
    }
    else
    {
        // Memory-mapped file already existed.
        RETAILMSG(1, (TEXT("[RIL] RHA_Init *** Sequent call of CreateFileMapping(MFPRMDB_SHARED_FILENAME)! \r\n")));
        bFirstInit = FALSE;
    }

    // Retrieve the local handle of the global shared memory-mapped file
    gpMfpRMDb = (P_XLLP_MFP_RM_DB_ID_T)MapViewOfFile(gMfpRMDbHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0 );
    if (!gpMfpRMDb)
    {
        RETAILMSG(1, (TEXT("[RIL] RHA_Init *** Fail to MapViewOfFile(m_MfpRMDbHandle)\r\n")));
        return;
    }

    if (TRUE == bFirstInit) {
        // Need to Initialize RM    
        if (XLLP_STATUS_SUCCESS != XllpMfpResourceManagerInit((P_XLLP_MFP_RM_DB_ID_T)gpMfpRMDb))
        {
            RETAILMSG(1, (TEXT("[RIL] RHA_Init *** Fail to XllpMfpResourceManagerInit(m_pMfpRMDb)\r\n")));
            return;
        }
    }


    XllpClockEnable((P_XLLP_CLKMGR_T)gpDCCLKReg, XLLP_CLK_I2C, XLLP_TRUE);
    gpI2CRegs->XLLP_ICR = XLLP_ICR_UR;
    XllpI2cInit((XLLP_I2C_T *)gpI2CRegs, (P_XLLP_VUINT32_T)gpMFPRegs, (P_XLLP_MFP_RM_DB_ID_T)gpMfpRMDb, 0);  //mfp_rm_db

    RETAILMSG(1, (TEXT("[RIL] ***RHA_Init Init Completed!\r\n")));
    g_fRHADLLInitFlag = TRUE;
    return;    
}

//
// Last function called by the RIL before unloading of the library
//
void RHA_DeInit(void)
{
    if (gpDCCLKReg)
    {
        MmUnmapIoSpace((PVOID)gpDCCLKReg, sizeof(XLLP_CLKMGR_T));
        gpDCCLKReg = NULL;
    }

    if (gpI2CRegs)
    {
        MmUnmapIoSpace((PVOID)gpI2CRegs, sizeof(XLLP_I2C_T));
        gpI2CRegs = NULL;
    }

    if (gpOSTRegs)
    {
        MmUnmapIoSpace((PVOID)gpOSTRegs, sizeof(XLLP_OST_T));
        gpOSTRegs = NULL;
    }


    if (gpMFPRegs)
    {
        MmUnmapIoSpace((PVOID)gpMFPRegs, RHA_MFP_TMP_SIZE);
        gpMFPRegs = NULL;
    }

    if (gpMfpRMDb)
    {
        UnmapViewOfFile((LPCVOID)gpMfpRMDb);
        gpMfpRMDb = NULL;
    }
    
    if (gMfpRMDbHandle)
    {
        CloseHandle(gMfpRMDbHandle);
        gMfpRMDbHandle = NULL;
    }

    g_fRHADLLInitFlag = FALSE;

}


#if(GPIO_EXPANDER == MAX7321)
//
// Switches on the power to the radio module
//
BOOL RHA_RadioPwrOn(void)
{
    RETAILMSG(1, (TEXT("+RHA_RadioPwrOn()\r\n")));	
	
    /*******************************************************************************************
                        Configure IGT_N to power on the radio
    *******************************************************************************************/
    //configure Configuration Port 0 Bit 0 (C0.0, IGT_N) as output
#if 0 
        if(GPX_SetDirection(XLLP_GPIO_IGT_N, XLLP_GPIO_DIRECTION_OUT) != XLLP_STATUS_SUCCESS)
        {
            RETAILMSG(1, (_T("Set XLLP_GPIO_IGT_N DIR Fail\r\n")));
        }
#endif       
	//configure Output IGT_N(P0) as low to turn on the modem
	if(GPX_SetOutputLevel(XLLP_GPIO_IGT_N, XLLP_LO) != XLLP_STATUS_SUCCESS)
	{
	    RETAILMSG(1, (_T("Set XLLP_GPIO_IGT_N HI FAIL\r\n")));
	}     

	RETAILMSG(1, (TEXT("[RIL] ***RHA_RadioPwrOn GPIO expander IGT_N(P0) as low Done. Then Wait 410 ms\r\n")));

	//configure EMERG_RST_N(P1) as low first
	GPX_SetOutputLevel(XLLP_GPIO_EMERG_RST_N, XLLP_LO);
	Sleep(120);
	//configure EMERG_RST_N(P1) as high
	GPX_SetOutputLevel(XLLP_GPIO_EMERG_RST_N, XLLP_HI);

	//configure LS_EN_N(P2) as low
	GPX_SetOutputLevel(XLLP_GPIO_LS_EN_N, XLLP_LO);
	
	//configure GPIO_RFU<0>(P3) as high
	GPX_SetOutputLevel(XLLP_GPIO_GPIO_RFU0, XLLP_HI);
	
	//configure REV_ID<0>(P4) as high
	GPX_SetOutputLevel(XLLP_GPIO_REV_ID0, XLLP_HI);
	
	//configure REV_ID<1>(P5) as high
	GPX_SetOutputLevel(XLLP_GPIO_REV_ID1, XLLP_HI);
	
	//configure REV_ID<2>(P6) as high
	GPX_SetOutputLevel(XLLP_GPIO_REV_ID2, XLLP_HI);
	
	//configure  PWR_IND_N(P7) as high
	GPX_SetOutputLevel(XLLP_GPIO_PWR_IND_N, XLLP_HI);
	
	Sleep(410);

	//configure Output IGT_N(P0) as high to turn on the modem
	if(GPX_SetOutputLevel(XLLP_GPIO_IGT_N, XLLP_HI) != XLLP_STATUS_SUCCESS)
	{
	    RETAILMSG(1, (_T("Set XLLP_GPIO_IGT_N HI FAIL\r\n")));
	}     

	RETAILMSG(1, (TEXT("[RIL] ***RHA_RadioPwrOn GPIO expander IGT_N(P0) as high Done. \r\n")));
	
	// PWR_IND_N(P7)(an input pin for max3721) should be low after power on modem
	XLLP_LEVEL_T pwr_int_n_level;
	if(GPX_GetLevel(XLLP_GPIO_PWR_IND_N, &pwr_int_n_level) != XLLP_STATUS_SUCCESS)
	{
	    RETAILMSG(1, (_T("Get XLLP_GPIO_PWR_IND_N level FAIL\r\n")));
		g_fRadioOn = FALSE;
	}

	if(pwr_int_n_level==XLLP_HI){
		g_fRadioOn = FALSE;
		RETAILMSG(1, (_T("PWR_IND_N level is high, turn on modem fail\r\n")));
	}else{
		g_fRadioOn = TRUE;
		RETAILMSG(1, (_T("PWR_IND_N level is low, turn on modem success\r\n")));
	}
		
	RETAILMSG(1, (TEXT("-RHA_RadioPwrOn()\r\n")));
	return TRUE;
}

#elif(GPIO_EXPANDER == PCA9539BS)
//
// Switches on the power to the radio module
//
BOOL RHA_RadioPwrOn(void)
{
    int init_status;
    XLLP_BOOL_T bSENDSTOP = XLLP_TRUE;
    unsigned char buffer[2];

    DEBUGMSG(ZONE_FUNCTION, (TEXT("+RHA_RadioPwrOn()\r\n")));
    
    if ((!gpI2CRegs) || (!gpOSTRegs))
    {
        RETAILMSG(1, (TEXT("[RIL] ***RHA_RadioPwrOn Failed (gpI2CRegs or gpOSTRegs is NULL) \r\n")));
        return FALSE;
    }

    /*******************************************************************************************
                        Configure IGT_N to power on the radio
    *******************************************************************************************/
    //configure Configuration Port 0 Bit 0 (C0.0, IGT_N) as output
    buffer[0] = 0x6;
    buffer[1] = 0xFE;

    init_status = XllpI2CWrite((P_XLLP_I2C_T)(gpI2CRegs), (P_XLLP_OST_T)(gpOSTRegs), (0xEE >>1), buffer, 2, bSENDSTOP);

    if (init_status != XLLP_STATUS_SUCCESS)
    {
        RETAILMSG(1, (TEXT("[RIL] ***Failed to configure GPIO expander (C0.0) as output \r\n")));
        return FALSE;
    }

    //RETAILMSG(1, (TEXT("[RIL] ***configure GPIO expander (C0.0) as output Done\r\n")));

    //configure Output Port 0 Bit 0 (O0.0) as low to turn on the modem
    buffer[0] = 0x2;
    buffer[1] = 0xFE;
    
    init_status = XllpI2CWrite((P_XLLP_I2C_T)(gpI2CRegs), (P_XLLP_OST_T)(gpOSTRegs), (0xEE >>1), buffer, 2, bSENDSTOP);

    if (init_status != XLLP_STATUS_SUCCESS)
    {
        RETAILMSG(1, (TEXT("[RIL] ***Failed to set GPIO expander (O0.0) as low \r\n")));
        return FALSE;
    }

    RETAILMSG(1, (TEXT("[RIL] ***RHA_RadioPwrOn GPIO expander (O0.0) as low Done. Then Wait 400 ms\r\n")));

    Sleep(410);

    //configure Output Port 0 Bit 0 (O0.0) as high to turn on the modem
    buffer[0] = 0x2;
    buffer[1] = 0xFF;
    
    init_status = XllpI2CWrite((P_XLLP_I2C_T)(gpI2CRegs), (P_XLLP_OST_T)(gpOSTRegs), (0xEE >>1), buffer, 2, bSENDSTOP);

    if (init_status != XLLP_STATUS_SUCCESS)
    {
        RETAILMSG(1, (TEXT("[RIL] ***Failed to set GPIO expander (O0.0) as high \r\n")));
        return FALSE;
    }

    RETAILMSG(1, (TEXT("[RIL] ***RHA_RadioPwrOn GPIO expander (O0.0) as high Done\r\n")));

    g_fRadioOn = TRUE;
    DEBUGMSG(ZONE_FUNCTION, (TEXT("-RHA_RadioPwrOn()\r\n")));
    return TRUE;
}
#endif

#if(GPIO_EXPANDER == MAX7321)
//
// Switches off the power to the radio module
//
BOOL RHA_RadioPwrOff(void)
{

    // Switch off power to the radio
    RETAILMSG(1, (TEXT("+RHA_RadioPwrOff()\r\n")));

    //configure Configuration Port 0 Bit 0 (C0.1, EMERG_RST_N) as output
#if 0 
        if(GPX_SetDirection(XLLP_GPIO_EMERG_RST_N, XLLP_GPIO_DIRECTION_OUT) != XLLP_STATUS_SUCCESS)
        {
            RETAILMSG(1, (_T("Set XLLP_GPIO_EMERG_RST_N DIR Fail\r\n")));
        }
#endif       

    //configure Output EMERG_RST_N(P1) as low to turn off the modem
    if(GPX_SetOutputLevel(XLLP_GPIO_EMERG_RST_N, XLLP_LO) != XLLP_STATUS_SUCCESS)
    {
        RETAILMSG(1, (_T("Set XLLP_GPIO_EMERG_RST_N LO FAIL\r\n")));
    }     


    RETAILMSG(1, (TEXT("[RIL] ***RHA_RadioPwrOff GPIO expander EMERG_RST_N(P1) as low Done. Then Wait 10 ms\r\n")));

    Sleep(15);
    if(GPX_SetOutputLevel(XLLP_GPIO_EMERG_RST_N, XLLP_HI) != XLLP_STATUS_SUCCESS)
    {
        RETAILMSG(1, (_T("Set XLLP_GPIO_EMERG_RST_N HI FAIL\r\n")));
    }     

    RETAILMSG(1, (TEXT("[RIL] ***RHA_RadioPwrOff GPIO expander EMERG_RST_N(P1) as high Done.\r\n")));

	/*
	after releasing the EMERG_RST line the module restarts if IGT is held low for at least 400ms. 
	Otherwise, if IGT is not low the module switches off.
	*/
	
	g_fRadioOn = FALSE;
    RETAILMSG(1, (TEXT("-RHA_RadioPwrOff()\r\n")));
    return TRUE;
}

#elif(GPIO_EXPANDER == PCA9539BS)
//
// Switches off the power to the radio module
//
BOOL RHA_RadioPwrOff(void)
{
    int init_status;
    XLLP_BOOL_T bSENDSTOP = XLLP_TRUE;
    unsigned char buffer[2];

    // Switch off power to the radio
    DEBUGMSG(ZONE_FUNCTION, (TEXT("+RHA_RadioPwrOff()\r\n")));

    if ((!gpI2CRegs) || (!gpOSTRegs))
    {
        RETAILMSG(1, (TEXT("[RIL] ***RHA_RadioPwrOff Failed (gpI2CRegs or gpOSTRegs is NULL) \r\n")));
        return FALSE;
    }

    //configure Configuration Port 0 Bit 0 (C0.1, EMERG_RST_N) as output
    buffer[0] = 0x6;
    buffer[1] = 0xFD;

    init_status = XllpI2CWrite((P_XLLP_I2C_T)(gpI2CRegs), (P_XLLP_OST_T)(gpOSTRegs), (0xEE >>1), buffer, 2, bSENDSTOP);

    if (init_status != XLLP_STATUS_SUCCESS)
    {
        RETAILMSG(1, (TEXT("[RIL] ***Failed to configure GPIO expander (C0.1) as output \r\n")));
        return FALSE;
    }

    //RETAILMSG(1, (TEXT("[RIL] ***configure GPIO expander (C0.1) as output Done\r\n")));

    //configure Output Port 0 Bit 0 (O0.1) as low to turn on the modem
    buffer[0] = 0x2;
    buffer[1] = 0xFD;
    
    init_status = XllpI2CWrite((P_XLLP_I2C_T)(gpI2CRegs), (P_XLLP_OST_T)(gpOSTRegs), (0xEE >>1), buffer, 2, bSENDSTOP);

    if (init_status != XLLP_STATUS_SUCCESS)
    {
        RETAILMSG(1, (TEXT("[RIL] ***Failed to set GPIO expander (O0.1) as low \r\n")));
        return FALSE;
    }

    RETAILMSG(1, (TEXT("[RIL] ***RHA_RadioPwrOff GPIO expander (O0.1) as low Done. Then Wait 10 ms\r\n")));

    Sleep(15);

    //configure Output Port 0 Bit 0 (O0.1) as high to turn on the modem
    buffer[0] = 0x2;
    buffer[1] = 0xFF;
    
    init_status = XllpI2CWrite((P_XLLP_I2C_T)(gpI2CRegs), (P_XLLP_OST_T)(gpOSTRegs), (0xEE >>1), buffer, 2, bSENDSTOP);

    if (init_status != XLLP_STATUS_SUCCESS)
    {
        RETAILMSG(1, (TEXT("[RIL] ***Failed to set GPIO expander (O0.1) as high \r\n")));
        return FALSE;
    }

    RETAILMSG(1, (TEXT("[RIL] ***RHA_RadioPwrOff GPIO expander (O0.1) as high Done\r\n")));

    g_fRadioOn = FALSE;
    DEBUGMSG(ZONE_FUNCTION, (TEXT("-RHA_RadioPwrOff()\r\n")));
    return TRUE;
}
#endif


//
// Returns the current state of the radio power
//
BOOL RHA_IsRadioPwrOn(void)
{
    DEBUGMSG(ZONE_FUNCTION, (TEXT("+RHA_IsRadioPwrOn()\r\n")));
    DEBUGMSG(ZONE_FUNCTION, (TEXT("-RHA_IsRadioPwrOn()\r\n")));
    return g_fRadioOn;
}

//
// Performs the actions required to route the voice audio to the user
//
BOOL RHA_ActivateVoicePath(DWORD dwTxAudioMode, DWORD dwRxAudioMode)
{
    MMRESULT waveFuncRet = MMSYSERR_NOERROR;

    // Signal the audio driver that a voice call is starting
    /* Send message to wave for phone path setup */
    waveFuncRet = waveOutMessage(0, WPDM_PRIVATE_SETUP_PHONE_PATH, 0, 0);

    if (MMSYSERR_NOERROR != waveFuncRet)
    {
        RETAILMSG(1, (TEXT("[RIL] RHA_ActivateVoicePath *** Failed (waveOutMessage (WPDM_PRIVATE_SETUP_PHONE_PATH, waveFuncRet = %d)) \r\n"), waveFuncRet));    
        return FALSE;
    }


    DEBUGMSG(ZONE_FUNCTION, (TEXT("-RHA_ActivateVoicePath()\r\n")));
    return TRUE;
}

//
// Performs the actions required to route the normal audio to the user
//
BOOL RHA_DeactivateVoicePath(void)
{
    MMRESULT waveFuncRet = MMSYSERR_NOERROR;
    DEBUGMSG(ZONE_FUNCTION, (TEXT("+RHA_DeactivateVoicePath()\r\n")));

    // Signal the audio driver that a voice call is ending
    waveFuncRet = waveOutMessage(0, WPDM_PRIVATE_DISABLE_PHONE_PATH, 0, 0);

    if (MMSYSERR_NOERROR != waveFuncRet)
    {
        RETAILMSG(1, (TEXT("[RIL] RHA_DeactivateVoicePath *** Failed (waveOutMessage (WPDM_PRIVATE_DISABLE_PHONE_PATH, waveFuncRet = %d)) \r\n"), waveFuncRet));    
        return FALSE;
    }

    DEBUGMSG(ZONE_FUNCTION, (TEXT("-RHA_DeactivateVoicePath()\r\n")));
    return TRUE;
}

//
//
//
BOOL RHA_AdjustTxVolume(DWORD dwAudioMode, DWORD dwVolume)
{
    DEBUGMSG(ZONE_FUNCTION, (TEXT("+RHA_AdjustTxVolume()\r\n")));

    return TRUE;
}

//
//
//
BOOL RHA_AdjustRxVolume(DWORD dwAudioMode, DWORD dwVolume)
{
    DEBUGMSG(ZONE_FUNCTION, (TEXT("+RHA_AdjustRxVolume()\r\n")));

    return TRUE;
}

//
//
//
BOOL RHA_GetRHAVersion(DWORD *pdwVersion)
{
    DWORD   dwHandle, dwSize, i;
    PDWORD  pvsVersionInfo;
    VS_FIXEDFILEINFO    *pvsFixedFileInfo;
    DWORD   dwMSVer, dwLSVer;

    DEBUGMSG(ZONE_FUNCTION, (TEXT("+RHA_GetRHAVersion()\r\n")));

    // Fetch the size of the version structure
    dwSize = GetFileVersionInfoSize(TEXT("RHA.DLL"), &dwHandle);

    // Allocate some memory for it
    pvsVersionInfo = (PDWORD)LocalAlloc(LPTR, dwSize);

    // Fetch the version structure
    GetFileVersionInfo(TEXT("RHA.DLL"), dwHandle, dwSize, pvsVersionInfo);

    // Search for the signature
    for(i=0;i<dwSize/4;i++)
    {
        if(pvsVersionInfo[i] == VS_FFI_SIGNATURE)pvsFixedFileInfo = (VS_FIXEDFILEINFO*)&pvsVersionInfo[i];
    }

    DEBUGMSG(ZONE_FUNCTION, (TEXT("Version LS = 0x%X  MS = 0x%X\r\n"), pvsFixedFileInfo->dwFileVersionLS, pvsFixedFileInfo->dwFileVersionMS));

    // Read the version info
    dwMSVer = pvsFixedFileInfo->dwFileVersionMS;
    dwLSVer = pvsFixedFileInfo->dwFileVersionLS;

    // Construct a 32 bit version number
    *pdwVersion = ((dwMSVer&0x00FF0000)<<8) + ((dwMSVer&0x000000FF)<<16) + ((dwLSVer&0x00FF0000)>>8) + (dwLSVer&0x000000FF);

    // Free the memory
    LocalFree(pvsVersionInfo);

    DEBUGMSG(ZONE_FUNCTION, (TEXT("-RHA_GetRHAVersion()\r\n")));

    return TRUE;
}

//
//
//
BOOL RHA_ConfirmAudioMode(DWORD *dwTxAudioMode, DWORD *dwRxAudioMode)
{
    DEBUGMSG(ZONE_FUNCTION, (TEXT("+RHA_ConfirmAudioMode()\r\n")));

        // Purpose of this function:
        // The Microsoft TAPI sets the audio device for each voice call to
        // RIL_AUDIO_HANDSET. Since it is not possible to configure the audio
        // device via TAPI, the RIL tests via this RHA-API which audio device
        // is valid. In the following example the RHA tests if the head set is
        // inserted an changes the audio device to RIL_AUDIO_HEADSET.
        // Example:
        //if (*dwTxAudioMode == RIL_AUDIO_HANDSET && RHA_IsHeadSetInserted()) {
        //        *dwTxAudioMode = RIL_AUDIO_HEADSET;
        //        *dwRxAudioMode = RIL_AUDIO_HEADSET;
        //        return FALSE;
        // The function RHA_IsHeadSetInserted() has to be implemented by the customer.
        //}

        // Default: we confirm the given values.
    return TRUE;
}

//
// Function to overwrite the default behaviour of the RIL internal power
// management. See Rgaapi.h for a detailed description of the RIL
// power management. Simply return the value passed in the parameter
// "dwNewDefaultModuleState" for any call to use the default power management.
//
DWORD RHA_SystemPowerChange(CEDEVICE_POWER_STATE CurrPwrState, CEDEVICE_POWER_STATE NewPwrState, DWORD dwCurrModuleState, DWORD dwNewDefaultModuleState, BOOL fOngoing, BOOL fQuery)
{
    DEBUGMSG(ZONE_FUNCTION, (TEXT("+RHA_SystemPowerChange()\r\n")));

  return dwNewDefaultModuleState;
}

//
//
//
#ifdef DEBUG_FILE
int DbgWrite(LPWSTR lpszFmt, ...)
{
    int count, i;
    va_list ap;
    WCHAR   UniBuffer[1024];
    char    AnsiBuffer[1024];
    char    time[32];
    DWORD   dwBytes;
    HANDLE  hDebugFile;

    va_start(ap, lpszFmt);
    count = wvsprintf(UniBuffer, lpszFmt, ap);
    va_end(ap);

    if (count > 0 && count < 1024)
    {
        EnterCriticalSection(&csDbgCritSect);
        hDebugFile = CreateFile((TEXT("\\Windows\\MuxDbg.log")), GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, 0, NULL);
        if(hDebugFile == (HANDLE)-1) return 0;
        SetFilePointer(hDebugFile, 0, 0, FILE_END );
        sprintf(time, "%dms : ", GetTickCount());
        WriteFile(hDebugFile, time, strlen(time), &dwBytes, NULL);
        for(i=0; i<count; i++)AnsiBuffer[i] = (char)UniBuffer[i];

        WriteFile(hDebugFile, AnsiBuffer, count, &dwBytes, NULL);

        CloseHandle(hDebugFile);
        LeaveCriticalSection(&csDbgCritSect);
    }
    return count;
}
#endif

